package com.systemframework.sys.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.operator.Equal;
import cn.zhxu.bs.util.MapBuilder;
import cn.zhxu.bs.util.MapUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.systemframework.constants.Constants;
import com.systemframework.enums.ResultCodeEnum;
import com.systemframework.exception.ResultException;
import com.systemframework.redis.RedisCache;
import com.systemframework.sys.dto.request.LoginRequestDTO;
import com.systemframework.sys.dto.request.SysUserPsdResponseDTO;
import com.systemframework.sys.dto.request.SysUserRequestDTO;
import com.systemframework.sys.dto.response.PermissionResponseDTO;
import com.systemframework.sys.dto.response.SysRoleMarkResponseDTO;
import com.systemframework.sys.dto.response.SysUserResponseDTO;
import com.systemframework.sys.entity.SysUser;
import com.systemframework.sys.entity.SysUserRole;
import com.systemframework.sys.mapper.SysUserMapper;
import com.systemframework.sys.service.SysUserRoleService;
import com.systemframework.sys.service.SysUserService;
import com.systemframework.upload.FileUploadConfig;
import com.systemframework.util.MD5;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author summer
 * @date 2023-03-08 14:24
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {



    @Override
    public Page<SysUserResponseDTO> findLists(SysUserRequestDTO sysUserRequestDTO) {
        Page<SysUserResponseDTO> page=new Page<>(sysUserRequestDTO.getPageNum(),sysUserRequestDTO.getPageSize());
        page=this.baseMapper.findLists(sysUserRequestDTO,page);
        return page;
    }

    private final RedisCache redisCache;

    private final CodeGenerator codeGenerator;

    @Override
    public SysUserResponseDTO login(LoginRequestDTO loginRequestDTO) {
        String captchaCode = redisCache.get(Constants.VERIFICATION_CODE + loginRequestDTO.getCaptchaKey());
        if(StrUtil.isEmpty(captchaCode)){
            throw new ResultException("验证码已过期,刷新验证码");
        }
        if(!codeGenerator.verify(captchaCode,loginRequestDTO.getCaptchaCode())){
            throw new ResultException("验证码输入错误,请重新输入");
        }
        LambdaQueryWrapper<SysUser> eq = Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUsername, loginRequestDTO.getUsername());
        SysUser sysUser = this.getOne(eq);

        if(ObjectUtil.isEmpty(sysUser) || !MD5.aesEncrypt(sysUser.getUsername(),loginRequestDTO.getPassword()).equals(sysUser.getPassword())){
            throw new ResultException(ResultCodeEnum.ERROR_USER_NAME_PASS.msg());
        }
        if(sysUser.getState().equals(Constants.ONE)){
            throw new ResultException(ResultCodeEnum.USER_EXCEPTION.msg());
        }
        SysUserResponseDTO sysUserResponseDTO=new SysUserResponseDTO();
        BeanUtil.copyProperties(sysUser,sysUserResponseDTO);
        return sysUserResponseDTO;
    }

    @Override
    public SysUserResponseDTO info() {
        SysUser byId = this.getById(StpUtil.getLoginIdAsInt());
        SysUserResponseDTO sysUserResponseDTO = Convert.convert(SysUserResponseDTO.class, byId);
        sysUserResponseDTO.setRoleLists(roleMarkLists(StpUtil.getLoginIdAsInt()));
        sysUserResponseDTO.setPermissionLists(permissionLists(StpUtil.getLoginIdAsInt()));
        return sysUserResponseDTO;
    }

    private final SysUserRoleService sysUserRoleService;


    @Override
    public void resetPsd(SysUserRequestDTO sysUserRequestDTO) {
        SysUser sysUser = this.getById(sysUserRequestDTO.getId());

    }

    @Override
    public void saveUser(SysUserRequestDTO sysUserRequestDTO) {
        SysUser entity = Convert.convert(SysUser.class, sysUserRequestDTO);
        if(ObjectUtil.isEmpty(entity.getId())){
            entity.setPassword(MD5.aesEncrypt(entity.getUsername(), Constants.DEFAULT_PASS_WORD));
            SysUser sysUser = this.getOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUsername, entity.getUsername()));
            if(ObjectUtil.isNotEmpty(sysUser)){
                throw new ResultException("用户账号已存在请重新输入");
            }
         }

        this.saveOrUpdate(entity);

        if(CollUtil.isNotEmpty(sysUserRequestDTO.getRoleIds())){
            List<SysUserRole> lists=ListUtil.list(true);
            sysUserRequestDTO.getRoleIds().forEach(roleId->{
                lists.add(new SysUserRole(entity.getId(),roleId));
            });
            sysUserRoleService.saveUserRole(lists,entity.getId());
        }

    }

    @Override
    public void changeUser(Integer id) {
        this.baseMapper.changeUser(id);
    }

    @Override
    public void updatePsd(SysUserPsdResponseDTO sysUserPsdResponseDTO) {
        if(!sysUserPsdResponseDTO.getNewPsd().equals(sysUserPsdResponseDTO.getPassword())){
            throw new ResultException("两次密码输入不一样,请重新输入");
        }
        SysUser sysUser = this.getById(Convert.toInt(StpUtil.getLoginId()));
        String psd = MD5.aesEncrypt(sysUser.getUsername(), sysUserPsdResponseDTO.getOldPsd());
        if(!psd.equals(sysUser.getPassword())){
            throw new ResultException("原始密码输入错误,请重新输入");
        }
        String newPsd = MD5.aesEncrypt(sysUser.getUsername(), sysUserPsdResponseDTO.getNewPsd());
        sysUser.setPassword(newPsd);
        this.saveOrUpdate(sysUser);
    }

    private final BeanSearcher beanSearcher;

    @Override
    public List<String> roleMarkLists(Integer userId) {
        Map<String, Object> build = MapUtils.builder().
                field(SysRoleMarkResponseDTO::getUserId,userId).op(Equal.class).build();
        List<SysRoleMarkResponseDTO> sysRoleMarkResponseDTOS = beanSearcher.searchList(SysRoleMarkResponseDTO.class, build);
        return sysRoleMarkResponseDTOS.stream().map(sysRoleMarkResponseDTO -> sysRoleMarkResponseDTO.getRole()).collect(Collectors.toList());
    }

    @Override
    public List<String> permissionLists(Integer userId) {
        Map<String, Object> build = MapUtils.builder().field(PermissionResponseDTO::getUserId,userId).op(Equal.class)
                .field(PermissionResponseDTO::getType,3).op(Equal.class).build();
        List<PermissionResponseDTO> permissionResponseDTOS = beanSearcher.searchList(PermissionResponseDTO.class, build);
        return permissionResponseDTOS.stream().map(permissionResponseDTO -> permissionResponseDTO.getPermission()).collect(Collectors.toList());
    }
     @Override
    public SysUserResponseDTO findById(Integer id) {
         SysUser sysUser = this.getById(id);
         SysUserResponseDTO sysUserResponseDTO = Convert.convert(SysUserResponseDTO.class, sysUser);
         LambdaQueryWrapper<SysUserRole> eq = Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId, id);
         List<Integer> roleIds = sysUserRoleService.list(eq).stream().map(sysUserRole -> sysUserRole.getRoleId()).collect(Collectors.toList());
         sysUserResponseDTO.setRoleIds(roleIds);
         return sysUserResponseDTO;
    }
}
